home *** CD-ROM | disk | FTP | other *** search
/ BCI NET / BCI NET Dec 94.iso / archives / applications / wp / ags-261-030.lha / gs261gdevretina.c < prev    next >
C/C++ Source or Header  |  1993-07-15  |  14KB  |  538 lines

  1. /*
  2.  * NAME
  3.  *   gdevretina.c
  4.  *
  5.  * DESCRIPTION
  6.  *   GhostScript device-driver for the Macro-Systems
  7.  *   RETINA graphics board. Currently this driver does not work
  8.  *   with 16-Bit Color-Lookup-Tables
  9.  *
  10.  * LEGAL STATUS
  11.  *   GNUware
  12.  *
  13.  * AUTHOR
  14.  *   Andreas Heitmann
  15.  *
  16.  * EMAIL
  17.  *   andreas@gotcha.swb.de
  18.  *   ah@hrz.uni-kassel.de
  19.  *   ah@rbg.informatik.th-darmstadt.de
  20.  *
  21.  */
  22. #include <stdio.h>
  23. #include <string.h>
  24. #include <exec/types.h>
  25. #include <exec/memory.h>
  26. #include <exec/libraries.h>
  27. #include <graphics/gfx.h>
  28. #include <retina/retina.h>
  29. #include <retina/clib/retina_protos.h>
  30. #include "gs.h"
  31. #include "gxdevice.h"
  32. #include "gdevretina.h"
  33. #include "gsmatrix.h"
  34. #include <stdlib.h>
  35.  
  36. #define X_DPI 72
  37. #define Y_DPI 72
  38.  
  39. #define RETINA_LIB_VERSION 3
  40.  
  41. #if RETINA_LIB_VERSION<4
  42. #define FILLRECTHACK
  43. #endif
  44.  
  45. #define COPYMONOHACK
  46.  
  47. #ifdef COPYMONOHACK
  48. #define RETINA_COPY_MONO r_copy_mono
  49. #else
  50. #define RETINA_COPY_MONO r_fast_copy_mono
  51. #endif
  52.  
  53. void TEST(char *x)
  54. {
  55.  char test[3];
  56.  eprintf(x);
  57.  eprintf("\n");
  58.  fflush(stderr);
  59.  fgets(test,2,stdin);
  60. }
  61.  
  62. /* forward declarations */
  63. dev_proc_open_device(r_open_device);
  64. dev_proc_close_device(r_close_device);
  65. dev_proc_map_rgb_color(r_map_rgb_color_8_16);
  66. dev_proc_map_color_rgb(r_map_color_rgb_8_16);
  67. dev_proc_map_rgb_color(r_map_rgb_color_24);
  68. dev_proc_map_color_rgb(r_map_color_rgb_24);
  69. dev_proc_fill_rectangle(r_fill_rectangle);
  70. dev_proc_copy_mono(RETINA_COPY_MONO);
  71. dev_proc_copy_color(r_copy_color);
  72. dev_proc_draw_line(r_draw_line);
  73. dev_proc_get_initial_matrix(r_get_initial_matrix);
  74.  
  75. #define retina_procs_24 { r_open_device, r_get_initial_matrix, gx_default_sync_output, gx_default_output_page, r_close_device, r_map_rgb_color_24, r_map_color_rgb_24, r_fill_rectangle, gx_default_tile_rectangle, RETINA_COPY_MONO, r_copy_color, r_draw_line, gx_default_get_bits, gx_default_get_props, gx_default_put_props }
  76. #define retina_procs_16 { r_open_device, r_get_initial_matrix, gx_default_sync_output, gx_default_output_page, r_close_device, r_map_rgb_color_8_16, r_map_color_rgb_8_16, r_fill_rectangle, gx_default_tile_rectangle, RETINA_COPY_MONO, r_copy_color, r_draw_line, gx_default_get_bits, gx_default_get_props, gx_default_put_props }
  77. #define retina_procs_8  { r_open_device, r_get_initial_matrix, gx_default_sync_output, gx_default_output_page, r_close_device, r_map_rgb_color_8_16, r_map_color_rgb_8_16 , r_fill_rectangle, gx_default_tile_rectangle, RETINA_COPY_MONO, r_copy_color, r_draw_line, gx_default_get_bits, gx_default_get_props, gx_default_put_props }
  78.  
  79. private gx_device_procs gs_retina_procs_8  = retina_procs_8;
  80. private gx_device_procs gs_retina_procs_16 = retina_procs_16;
  81. private gx_device_procs gs_retina_procs_24 = retina_procs_24;
  82.  
  83. #define gs_retina_skel(procs,name,colors,mode) {sizeof(retina_device),&procs,name,0,0,XPPI,YPPI,no_margins,colors,FALSE,NULL,mode,0,NULL,NULL,NULL}
  84.  
  85. retina_device gs_retina8_device  = gs_retina_skel(gs_retina_procs_8, "retina8" ,dci_color( 8, 31,  4),MID_DEFAULT_08);
  86. retina_device gs_retina16_device = gs_retina_skel(gs_retina_procs_16,"retina16",dci_color(16,255,256),MID_DEFAULT_16);
  87. retina_device gs_retina24_device = gs_retina_skel(gs_retina_procs_24,"retina24",dci_color(24,255,256),MID_DEFAULT_24);
  88.  
  89. /** procedures **/
  90.  
  91. /* tests if the pixel coordinates have valid values */
  92. static boolean
  93. retina_is_valid_area(gx_device * dev, int x, int y, int width, int height)
  94. {
  95.  return x >= 0 && y >= 0 && x + width <= rdev->width && y + height <= rdev->height;
  96. }
  97.  
  98. /* Amiga library bases */
  99. struct RetinaBase *RetinaBase = NULL;
  100. struct GfxBase *GfxBase = NULL;
  101.  
  102.  
  103. void
  104. gs_retina_setrgb(gx_device *dev,byte r,byte g,byte b)
  105. {
  106.  rdev->palette[rdev->ncols][0]=r; 
  107.  rdev->palette[rdev->ncols][1]=g;
  108.  rdev->palette[rdev->ncols][2]=b;
  109.  rdev->ncols++; 
  110. }
  111.  
  112.  /*
  113.   * preallocate colors for video-modes with color-lookup tables
  114.   */
  115. int
  116. preallocate_colors(gx_device *dev)
  117. {
  118.  int res=0;
  119.  
  120.  switch (rdev->screenmode) {
  121.   case MID_DEFAULT_08:
  122.   case MID_DEFAULT_16:
  123.   rdev->palette =(byte (*)[3])calloc(1 << dev->color_info.depth, 3*sizeof(byte));
  124.   if (NULL != rdev->palette) {
  125.    gx_color_index color;
  126.    byte r, g, b;
  127.  
  128.    /* reset index counter */
  129.    rdev->ncols = 0;
  130.  
  131.    /* allocate black & white as first 2 colors */
  132.    gs_retina_setrgb(dev,0, 0, 0);
  133.    gs_retina_setrgb(dev,255, 255, 255);
  134.  
  135.    /* allocate evenly space color cube */
  136.    while (rdev->ncols < RGB_COLS) {
  137.     color = rdev->ncols - 1;
  138.     r = ((color & RED_MASK) >> (GREEN_BITS + BLUE_BITS))
  139.       * ((1 << dev->color_info.depth) - 1) / (RED_COLS - 1);
  140.     g = ((color&GREEN_MASK) >> BLUE_BITS)
  141.       * ((1 << dev->color_info.depth) - 1) / (GREEN_COLS - 1);
  142.     b = (color&BLUE_MASK)
  143.       * ((1 << dev->color_info.depth) - 1) / (RED_COLS - 1);
  144.     /* Retina_SetPalette(rdev->rs,rdev->ncols,r,g,b); */
  145.     gs_retina_setrgb(dev,r,g,b);
  146.    }
  147.  
  148.    /* load the color map */
  149.    Retina_LoadPalette(rdev->rs, 0, rdev->ncols, (UBYTE *) rdev->palette);
  150.   }
  151.   else {
  152.    eprintf("gs retina: no memory for colormap\n");
  153.    res = -1;
  154.   }
  155.   break;
  156.   default:
  157.  }
  158.  return res;
  159. }
  160.  
  161. int
  162. open_screen(gx_device *dev)
  163. {
  164.  int res=0;
  165.  
  166.  if(NULL!=(GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",0))) {
  167.   if(NULL!=(RetinaBase=(struct RetinaBase *)OpenLibrary
  168.      ("retina.library",RETINA_LIB_VERSION))) {
  169.    if (NULL !=(rdev->rs = Retina_OpenScreen(
  170.     rdev->width  == 0 ? RSCR_MAXWIDTH  : rdev->width,
  171.     rdev->height == 0 ? RSCR_MAXHEIGHT : rdev->height,
  172.     rdev->screenmode,
  173.     RSFF_AUTOADJUST | RSFF_DONTCLEARONOPEN | RSFF_DONTCLEARONCLOSE,
  174.     NULL))) {
  175.     Retina_ClearScreen(rdev->rs);
  176.     /*
  177.      * real screensize may have changed due to memory lack, so correct the
  178.      * variables
  179.      */
  180.     rdev->width = rdev->rs->_rs_Width;
  181.     rdev->height = rdev->rs->_rs_Height;
  182.    }
  183.    else {
  184.     eprintf("gs retina: can't open retina screen.\n");
  185.     res = -1;
  186.    }
  187.   }
  188.   else {
  189.    res = -1;
  190.    eprintf1("gs retina: can't open version %d of the retina.library.\n",
  191.         RETINA_LIB_VERSION);
  192.   }
  193.  }
  194.  else {
  195.   res = -1;
  196.   eprintf("gs retina: can't open graphics library.\n");
  197.  }
  198.  return res;
  199. }
  200.  
  201. void
  202. setup_rdev(gx_device *dev)
  203. {
  204.  rdev->wz_scale_x = (float)rdev->width / PRE_WIDTH;
  205.  rdev->wz_scale_y = (float)rdev->height / PRE_HEIGHT;
  206.  rdev->is_open = TRUE;
  207. }
  208.  
  209. int
  210. r_open_device(gx_device *dev)
  211. {
  212.  int res=0;
  213.  char buf[3];
  214.  
  215.  rdev->is_open=FALSE;
  216.  rdev->rs=NULL;
  217.  if(0==(res=open_screen(dev))) {
  218.   preallocate_colors(dev);
  219.   setup_rdev(dev);
  220.  }
  221.  return res;
  222. }
  223.  
  224. /*
  225.  * closes retina device
  226.  *  - close screen
  227.  *  - close library
  228.  */
  229. int
  230. r_close_device(gx_device * dev)
  231. {
  232.  /*
  233.   * free color palette, if allocated
  234.   */
  235.  switch (rdev->screenmode) {
  236.   case MID_DEFAULT_08:
  237.   case MID_DEFAULT_16:
  238.    if (rdev->palette != NULL) free(rdev->palette);
  239.    break;
  240.   case MID_DEFAULT_24:
  241.    break;
  242.  }
  243.  
  244.  /*
  245.   * close screen, if opened
  246.   */
  247.  if (rdev->rs != NULL) {
  248.   Retina_CloseScreen(rdev->rs);
  249.   rdev->is_open = FALSE;
  250.  }
  251.  
  252.  /*
  253.   * close libraries
  254.   */
  255.  if (RetinaBase != NULL) CloseLibrary((struct Library *)RetinaBase);
  256.  if (GfxBase != NULL)    CloseLibrary((struct Library *)GfxBase);
  257.  
  258.  /*
  259.   * exit without error
  260.   */
  261.  return 0;
  262. }
  263.  
  264. /*
  265.  * modified sun mapping routines
  266.  */
  267. gx_color_index
  268. r_map_rgb_color_24(gx_device * dev, gx_color_value r, gx_color_value g, gx_color_value b)
  269. {
  270.  return
  271.   (gx_color_value_to_byte(r)<<16)+
  272.   (gx_color_value_to_byte(g)<<8)+
  273.   gx_color_value_to_byte(b);
  274. }
  275.  
  276. gx_color_index
  277. r_map_rgb_color_8_16(gx_device * dev, gx_color_value r, gx_color_value g, gx_color_value b)
  278. {
  279.  gx_color_index ret = gx_no_color_index;
  280.  byte red_val, green_val, blue_val;
  281.  gx_color_index i;
  282.  static int warn = 1;
  283.  
  284.  /*
  285.   * Determine the RGB values at display resolution we ideally would want
  286.   * this color to be mapped into.
  287.   */
  288.  red_val  =gx_color_value_to_byte(r);
  289.  green_val=gx_color_value_to_byte(g);
  290.  blue_val =gx_color_value_to_byte(b);
  291.  
  292.  /*
  293.   * Look for an exact match among the colors already allocated. This
  294.   * includes the pre-allocated default color cube.
  295.   */
  296.  for (i = 0; i < rdev->ncols; i++) {
  297.   if (rdev->palette[i][0] == red_val &&
  298.       rdev->palette[i][1] == green_val &&
  299.       rdev->palette[i][2] == blue_val) {
  300.    ret = i;
  301.   }
  302.  }
  303.  if (ret == gx_no_color_index) {
  304.   if (rdev->ncols == (1 << dev->color_info.depth)) {
  305.    if (warn) {
  306.     eprintf("gs retina: last spare color map entry allocated\n");
  307.     warn = 0;
  308.    }
  309.   }
  310.   else {
  311.    Retina_SetPalette(rdev->rs, i, red_val, green_val, blue_val);
  312.    gs_retina_setrgb(dev,red_val, green_val, blue_val);
  313.    ret = i;
  314.   }                /* else alloc new color */
  315.  }                /* end if no spare colors */
  316.  return ret;
  317. }
  318.  
  319. /*
  320.  * map retina color index to ghostscript rgb-value
  321.  */
  322. int
  323. r_map_color_rgb_24(gx_device * dev, gx_color_index color, ushort prgb[3])
  324. {
  325.  prgb[0]=gx_color_value_from_byte((color>>16)&0xff);
  326.  prgb[1]=gx_color_value_from_byte((color>> 8)&0xff);
  327.  prgb[2]=gx_color_value_from_byte( color     &0xff);
  328.  return 0;
  329. }
  330.  
  331. int
  332. r_map_color_rgb_8_16(gx_device * dev, gx_color_index color, ushort prgb[3])
  333. {
  334.  prgb[0]=gx_color_value_from_byte(rdev->palette[color][0]);
  335.  prgb[1]=gx_color_value_from_byte(rdev->palette[color][1]);
  336.  prgb[2]=gx_color_value_from_byte(rdev->palette[color][2]);
  337.  return 0;
  338. }
  339.  
  340. /*
  341.  * fill rectangle with color
  342.  */
  343. int 
  344. r_fill_rectangle(gx_device * dev, int x, int y, \
  345.   int width, int height, gx_color_index color)
  346. {
  347.  int res = 0;
  348.  
  349.  if (retina_is_valid_area(dev, x, y, width, height)) {
  350. #ifdef FILLRECTHACK
  351.   switch (rdev->screenmode) {
  352.    case MID_DEFAULT_24:
  353. #endif
  354.     Retina_SetDrMd(rdev->rs, RDM_JAM1);
  355.     Retina_SetAPen(rdev->rs, color);
  356.     Retina_RectFill(rdev->rs, x, y, x + width, y + height);
  357. #ifdef FILLRECTHACK
  358.     break;
  359.     /*
  360.      * There is a bug in the RectFill routine of retina.library version 2.3
  361.      * in the 8 & 16 Bit color-mode so i can't use it.
  362.      *
  363.      * This bug has been fixed in Version 3.8 of retina.library
  364.      */
  365.    case MID_DEFAULT_08:
  366.    case MID_DEFAULT_16:
  367.     {
  368.      int xx;
  369.  
  370.      Retina_SetDrMd(rdev->rs, RDM_JAM1);
  371.      Retina_SetAPen(rdev->rs, color);
  372.      for (xx = x + width - 1; xx >= x; xx--)
  373.       Retina_Line(rdev->rs, xx, y, xx, y + height - 1);
  374.      break;
  375.     }
  376.   }
  377. #endif
  378.  }
  379.  else res = -1;
  380.  return res;
  381. }
  382.  
  383. /*
  384.  * draw line
  385.  */
  386. int 
  387. r_draw_line(gx_device * dev, int x0, int y0, int x1, int y1, \
  388.   gx_color_index color)
  389. {
  390.  int h;
  391.  
  392.  if (!(y1 == y0 && x1 == x0)) {
  393.   Retina_SetDrMd(rdev->rs, RDM_JAM1);
  394.   Retina_SetAPen(rdev->rs, color);
  395.   Retina_Line(rdev->rs, x0, y0, x1, y1);
  396.  }
  397.  return 0;
  398. }
  399.  
  400. #ifdef COPYMONOHACK
  401. int r_copy_mono
  402. (gx_device *dev,\
  403.  const unsigned char *data, int data_x, int raster, gx_bitmap_id id,\
  404.  int x, int y, int width, int height,\
  405.  gx_color_index color0, gx_color_index color1)
  406. {
  407.  boolean draw = TRUE;
  408.  int res = 0;
  409.  unsigned char *dp;      /* pointer to first byte of each line */
  410.  static gx_bitmap_id old_id = gx_no_bitmap_id;
  411.  unsigned char bit;      /* bitmask */
  412.  long byte;              /* byte number in scanline */
  413.  gx_color_index color;   /* actual color: color_c */
  414.  long ix, iy;            /* coordinates in data space */
  415.  int c;                  /* color index: 0..1 */
  416.  
  417.  /*
  418.   * this is a hack and has to be replaced in future versions of gdevretina.c
  419.   * 
  420.   * i am trying to replace this by a bitmap-copy but not before the
  421.   * next release of the retina-software
  422.   */
  423.  if (retina_is_valid_area(dev, x, y, width, height)) {
  424.   for (c = 0; c <= 1; c++) {
  425.    color = (c == 0) ? color0 : color1;
  426.    if (color != gx_no_color_index) {
  427.     dp = data;
  428.     for (iy = 0; iy < height; iy++) {
  429.      for (byte = 0, ix = 0; ix < width; byte++) {
  430.       for (bit = 1 << 7; bit && ix < width; ix++, bit >>= 1) {
  431.        if (dp[byte] & bit)
  432.         Retina_SetPixel(rdev->rs, x + ix, y + iy, color);
  433.       }
  434.      }
  435.      dp += raster;
  436.     }
  437.    }
  438.   }
  439.  }
  440.  else res = -1;
  441.  return res;
  442. }
  443. #endif
  444.  
  445. /*
  446.  * The following function is a replacement for the slow r_copy_mono routine.
  447.  * It still doesn't work because Retina_WriteBitMap doesn't support
  448.  * writing WBMMODE_STD BitMaps to 24Bit Screens.
  449.  * If the bug is fixed in newer versions of the retina.library i will
  450.  * undefine COPYMONOHACK :)
  451.  */
  452. #ifndef COPYMONOHACK
  453. int 
  454. r_fast_copy_mono(gx_device * dev, unsigned char *data, int data_x, \
  455.   int raster, gx_bitmap_id id, int x, int y, \
  456.   int width, int height, gx_color_index color0, \
  457.   gx_color_index color1)
  458. {
  459.  unsigned char pal[2 * 3];
  460.  static struct BitMap mybm;
  461.  int res = 0;
  462.  
  463.  if (retina_is_valid_area(dev, x, y, width, height)) {
  464.   InitBitMap(&mybm, 1, width, height);
  465. #ifdef DEBUG
  466.   printf("bm.bbr=%d\n", mybm.BytesPerRow);
  467.   printf("bm.row=%d\n", mybm.Rows);
  468.   printf("bm.flg=%d\n", mybm.Flags);
  469.   printf("bm.dpt=%d\n", mybm.Depth);
  470.   printf("x=%d   y=%d   w=%d   h=%d raster=%d\n", x, y, width, height, raster);
  471. #endif
  472.   /*
  473.    * correct the number of bytes per row, because gfx has it's own way to
  474.    * compute the number of bytes from the number of pixels in each line.
  475.    */
  476.   mybm.BytesPerRow = raster;
  477.   mybm.Planes[0] = (PLANEPTR) data;
  478. #ifdef DEBUG
  479.   {
  480.    int i, j;
  481.  
  482.    for (j = 0; j < height; j++) {
  483.     for (i = 0; i < raster; i++) {
  484.      printf("%02x ", *(mybm.Planes[0] + i + j * raster));
  485.     }
  486.     puts("");
  487.    }
  488.   }
  489. #endif
  490.   pal[0] = ((unsigned char *)&color0)[1];
  491.   pal[1] = ((unsigned char *)&color0)[2];
  492.   pal[2] = ((unsigned char *)&color0)[3];
  493.   pal[3] = ((unsigned char *)&color1)[1];
  494.   pal[4] = ((unsigned char *)&color1)[2];
  495.   pal[5] = ((unsigned char *)&color1)[3];
  496.   Retina_WriteBitMap(rdev->rs, &mybm, pal, x, y, width, WBMMODE_STD);
  497.  }
  498.  else
  499.   res = -1;
  500.  return res;
  501. }
  502. #endif
  503.  
  504. int
  505. r_copy_color(
  506.  gx_device *dev,\
  507.  const unsigned char *data, int data_x, int raster, gx_bitmap_id id,\
  508.  int x, int y, int width, int height)
  509. {
  510.  int res = 0;
  511.  
  512.  if (retina_is_valid_area(dev, x, y, width, height)) {
  513.   switch (rdev->screenmode) {
  514.    case MID_DEFAULT_24:
  515.     Retina_WriteRect(data, 0, 0, raster, RECTMODE_RGB, rdev->rs, x, y, width,
  516.       height, NULL);
  517.     break;
  518.    case MID_DEFAULT_08:
  519.     Retina_WriteRect(data, 0, 0, raster, RECTMODE_256, rdev->rs, x, y, width,
  520.       height, NULL);
  521.     break;
  522.   }
  523.  }
  524.  else
  525.   res = -1;
  526.  return res;
  527. }
  528.  
  529. void 
  530. r_get_initial_matrix(gx_device * dev, gs_matrix * m)
  531. {
  532.  /* scale the user coordinates with SCALE */
  533.  m->xy = m->yx = m->tx = 0;
  534.  m->xx = rdev->x_pixels_per_inch * SCALE * rdev->wz_scale_x /X_DPI;
  535.  m->yy = -rdev->y_pixels_per_inch * SCALE * rdev->wz_scale_y/Y_DPI;
  536.  m->ty = rdev->height;
  537. }
  538.